/*************************************************************************
 *   >      File Name: main_sub.c
 *   >    Description:   This file
 *   >         Author: Yang Xiaohan
 *   >           Mail: yangxiaohan_niki@163.com
 *   >   Created Time: Wed 20 Jul 2022 11:13:27 CST
 *   >   Changed Time: Wed 20 Jul 2022 11:13:27 CST
 *************************************************************************/

#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include "iniparser.h"
#include "dictionary.h"
#include "mosquitto.h"
#include "configini.h"

#define PATH  "../etc/tencentyun.ini"

int run_flag = 0;

void sig_handler(int signum)
{
	if(signum == SIGUSR1)
	{
		printf("catch SIGUSR1 signal.\n");
		run_flag = 1;
	}
}

void sub_connect_callback(struct mosquitto *mosq, void *obj,int rc)
{
	int					ret = -1;
	user_data			*mqtt;

	mqtt = (user_data *)obj;

	if(rc != 0)
	{
		printf("Connect refuse:%s.\n",strerror(errno));
		return;
	}
	else
	{
		ret = mosquitto_subscribe(mosq,NULL,mqtt->topic,2);
		if(ret != MOSQ_ERR_SUCCESS)
		{
			printf("subscribe topic failure!\n");
			exit(1);
		}
		printf("subscribe topic successfully!\n");
	}

}

void disconnect_callback(struct mosquitto *mosq,void *obj,int rc)
{
	printf("Callback on function: on_disconnect.\n");
	run_flag = 0;
}
void subscribe_callback(struct mosquitto *mosq,void *obj,int mid,int qos_count,const int * granted_qos)
{
	printf("Callback on function: on_subsribe.\n");

}
void message_callback(struct mosquitto *mosq,void *obj,const struct mosquitto_message *msg)
{
	printf("Callback on function: on_message.\n");
	printf("Recieve a message:%s from topic:%s.\n",(char *)msg->payload,(char *)msg->topic);
	if( 0 == strcmp(msg->payload, "quit"))
	{
		printf("Recieve the msg is null.\n");
		mosquitto_disconnect(mosq);
	}

}


void printf_usage(char *progname)
{
	printf("%s usage:\n",progname);
	printf("-d(--daemon:set program running on background.\n");
	printf("-h(--help:print this help information.\n");
	printf("Example: %s -h\n" ,progname);     
	return;

}

int main (int argc, char **argv)
{
	int						ret;
	char					*progname = basename(argv[0]);
	int						opt = -1;
	int						daemon_run = 0;
	int						log_fd;
	struct mosquitto		*mosq;
	user_data   			mqtt;

	struct option		options[] =
	{
		{"daemon",no_argument,NULL,'d'},
		{"help",no_argument,NULL,'h'},
		{NULL, 0, NULL, 0}
	};

	while((opt = getopt_long(argc,argv,"dh",options,NULL)) != -1)
	{
		switch(opt)
		{
			case 'd':
				daemon_run = 1;
				break;
			case 'h':
				printf_usage(argv[0]);
				return -1;
			default:
				break;
		}
	}

	//后台运行
	if(daemon_run)
	{
		printf("program %s running in the background\n",progname);
		if( (log_fd = open("../tmp/running.log",O_CREAT|O_RDWR, 0666)) < 0)
		{
			printf("open() log file failure:%s\n",strerror(errno));
			return -1;
		}
		dup2(log_fd, STDOUT_FILENO);//标准输出重定向到tencent.log文件中
		dup2(log_fd, STDERR_FILENO);//标准出错重定向到tencent.log文件中

		daemon(1,1);
	}
	signal(SIGUSR1,sig_handler);

	//载入解析文件
	memset(&mqtt, 0, sizeof(mqtt));
	ret = get_config(PATH, &mqtt, SUB);
	if(ret != 0)
	{
		printf("get_config() failure:%s.\n",strerror(errno));
		exit(1);
	}
	//mosquitto初始化
	mosquitto_lib_init();

	//创建mosquitto实例
	mosq = mosquitto_new(mqtt.clientid, true, (void *)&mqtt);
	if(mosq == NULL)
	{
		printf("Create a new client failure!\n");
		goto cleanup;
	}

	//设置客户端用户名和密码
	ret = mosquitto_username_pw_set(mosq,mqtt.username,mqtt.password);
	if(ret != MOSQ_ERR_SUCCESS)
	{
		printf("set username and password failure!\n");
		goto cleanup;
	}

	//登记回调函数
	mosquitto_connect_callback_set(mosq,sub_connect_callback);
	mosquitto_disconnect_callback_set(mosq,disconnect_callback);
	mosquitto_subscribe_callback_set(mosq,subscribe_callback);
	mosquitto_message_callback_set(mosq,message_callback);


	//连接服务器
	ret = mosquitto_connect(mosq,mqtt.brokeraddress,mqtt.brokerport,KEEP_ALIVE);
	if(ret != MOSQ_ERR_SUCCESS)
	{
		printf("mosquitto_connect failure:%s\n",strerror(errno));
		goto cleanup;
	}
	printf("Connect with server successfully!\n");
	
	printf("Start!\n");
	while(!run_flag)
	{
		//网络循环，连接成功调用回调函数
		ret = mosquitto_loop(mosq,-1,1);
		if(ret != MOSQ_ERR_SUCCESS)
		{
			printf("mosquitto_loop failure\n");
			goto cleanup;
		}

	}

cleanup:
	close(log_fd);
	mosquitto_destroy(mosq);
	mosquitto_lib_cleanup();
	return 0;
} 


